package xiaogang.enif.net;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import xiaogang.enif.utils.HttpManager;
import xiaogang.enif.utils.IOUtils;
import xiaogang.enif.utils.LogUtils;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;

public class WSTask extends AsyncTask<Void, Void, Object> {
    private int mAction;
    private String mErrorCode;
    private Object mParameter;

    private Context mContext;
    private TaskListener mTaskListener;
    private Exception mReason;
    private final LogUtils mLog = LogUtils.getLog(WSTask.class);

    public WSTask(Context context, TaskListener listener, int action, Object paramObject) {
        mContext = context;
        mTaskListener = listener;
        mParameter = paramObject;
        mAction = action;
    }

    @Override
    public Object doInBackground(Void... arg0) {
        Object result = null;
        try {
            @SuppressWarnings("unchecked")
            ArrayList<BasicNameValuePair> vps = (ArrayList<BasicNameValuePair>)mParameter;
            final String jsonString = request(mContext, "your url", vps);
            mLog.debug(jsonString);
            result = parseJson(jsonString);
            if (result != null && result instanceof String
                    && TextUtils.isDigitsOnly((String)result)) {
                mErrorCode = (String)result;
                return null;
            }
        } catch (Exception e) {
            mReason = e;
            mLog.error(e.getMessage());
            return null;
        }

        return result;
    }

    @Override
    public void onPostExecute(Object result) {
        if (mContext== null) {
            clearTask();
            return;
        }

        if (mContext instanceof Activity && ((Activity) mContext).isFinishing()) {
            clearTask();
            return;
        }

        if (result == null || mReason != null) {
            mTaskListener.onFailed(mAction, mErrorCode, mReason);
        } else {
            mTaskListener.onSuccess(mAction, result);
        }
        clearTask();
    }

    private String request(Context context, String url, ArrayList<BasicNameValuePair> vp)
            throws IOException {
        final HttpPost post = new HttpPost(url);
        post.setEntity(new UrlEncodedFormEntity(vp, "UTF_8"));

        InputStream in = null;
        HttpEntity entity = null;
        try {
            final HttpResponse response = HttpManager.execute(context, post);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                entity = response.getEntity();
                if (entity != null) {
                    in = entity.getContent();
                    return IOUtils.stream2String(in);
                }
            } else {
                post.abort();
                mLog.error("http code: " + response.getStatusLine().getStatusCode());
            }
            return null;
        } catch (IOException ex) {
            post.abort();
            throw ex;
        } catch (RuntimeException ex) {
            post.abort();
            throw ex;
        } finally {
            if(entity!=null) {
                entity.consumeContent();
            }
            IOUtils.closeStream(in);
        }
    }

    private Object parseJson(String jsonString) throws IOException {
        try {
            JSONObject jobj = new JSONObject(jsonString);
            if (jobj.has("errorcode")) {
                return jobj.optString("errorcode");
            }

            if (jobj.has("resultlist")) {
                ArrayList<HashMap<String, String>> arrList;
                arrList = new ArrayList<HashMap<String, String>>();
                JSONArray jsonArray = jobj.optJSONArray("resultlist");
                final int len = jsonArray.length();
                for (int i = 0; i < len; i++) {
                    final JSONObject obj = (JSONObject)jsonArray.opt(i);
                    arrList.add(parse2Map(obj));
                }
                return arrList;
            } else {
                return parse2Map(jobj);
            }
        } catch (JSONException e) {
            IOException ioe = new IOException("Invalid json String...");
            ioe.initCause(e);
            throw ioe;
        }
    }

    private HashMap<String, String> parse2Map(JSONObject jsonObj) throws IOException {
        final HashMap<String, String> hashMap = new HashMap<String, String>();
        @SuppressWarnings("unchecked")
        final Iterator<String> keyIter = jsonObj.keys();
        String key, value;
        while (keyIter != null && keyIter.hasNext()) {
            key = keyIter.next();
            value = jsonObj.optString(key);
            hashMap.put(key, value);
        }
        return hashMap;
    }

    private void clearTask() {
        mTaskListener = null;
        mParameter = null;
        mContext = null;
    }

    public interface TaskListener {
        public void onSuccess(int action, Object result);
        public void onFailed(int action, String errcode, Exception ex);
    }
}
